<template>
  <div>
    <div id="Map" ref="map"></div>
    <div ref="popup" class="popup">
      <span class="icon-close" @click="closePopup">❌</span>
      <div class="content" ref="coordinate">{{ currentCoordinate }}</div>
    </div>
  </div>
</template>

<script>
import VectorLayer from "ol/layer/Vector";
import VectorSource from "ol/source/Vector";
import Feature from "ol/Feature";
import { Draw } from "ol/interaction";
import { Style, Fill, Stroke, Circle, Icon } from "ol/style";
import { transform, fromLonLat, toLonLat } from "ol/proj";
import { Point, LineString } from "ol/geom";
import CAR from "../../assets/feiji.png";
import Overlay from "ol/Overlay";

import { Map, View, interaction, events } from "ol";
import TileLayer from "ol/layer/Tile";
import { defaults as defaultControls } from "ol/control";
import XYZ from "ol/source/XYZ";
import dataArr from "./glb/data";

let commonStyle = {
  boardStyle: new Style({
    image: new Icon({
      anchor: [0.5, 1],
      src: require("./glb/icon.png"),
      // src:require("../assets/images/position.png")
    }),
  }),
};
export default {
  data() {
    return {
      overlays: null,
      currentCoordinate: "",
      map: this.$route.params.map,
      layer: null,
      interaction: null,
      source: null,
      feature: null,
      coors: [], //路的转折点
      carPoint: [], //车还要走的点
      index: 0, //当前小车所在的路段
      timer: null,
      follow: false, //默认不聚焦
    };
  },
  methods: {
    //初始化地图
    initMap() {
      this.overlay = new Overlay({
        element: this.$refs.popup, // 弹窗标签，在html里
        autoPan: true, // 如果弹窗在底图边缘时，底图会移动
        autoPanAnimation: {
          // 底图移动动画
          duration: 250,
        },
      });
      this.map = new Map({
        target: "Map",
        controls: defaultControls({
          zoom: false,
        }).extend([]),
        layers: [
          new TileLayer(
            {
              source: new XYZ({
                url: "http://map.geoq.cn/ArcGIS/rest/services/ChinaOnlineStreetPurplishBlue/MapServer/tile/{z}/{y}/{x}",
                // "http://wprd0{1-4}.is.autonavi.com/appmaptile?lang=zh_cn&size=1&style=7&x={x}&y={y}&z={z}"
              }),
            },
            { zoomOffset: 1 }
          ),
        ],
        overlays: [this.overlay], // 把弹窗加入地图
        view: new View({
          center: fromLonLat([108.522097, 37.272848]),
          zoom: 4.7,
          // maxZoom: 4.7,
          // minZoom: 4.7,
        }),
      });
      this.mapClick();
    },
    //添加矢量图层
    async open() {
      //画轨迹线
      await this.drawLine();
      //开始动
      this.moveStart();
    },
    //轨迹线  把每个点连起来
    drawLine() {
      this.lineLayer = new VectorLayer({
        source: new VectorSource({
          features: [],
        }),
      });
      this.map.addLayer(this.lineLayer);
      let comDots = [];
      let featuresArr = []; //图像集
      let wireFeature = null;
      let boardFeature = null;
      dataArr.dataArr.forEach((item, index) => {
        comDots.push(item);
        wireFeature = new Feature({
          geometry: new LineString(comDots),
        });
        wireFeature.setStyle(
          new Style({
            stroke: new Stroke({
              // 设置边的样式
              color: "rgb(21, 106, 158)",
              width: 1,
            }),
          })
        );
        this.lineLayer.getSource().addFeatures([wireFeature]);
        comDots.forEach((item) => {
          boardFeature = new Feature({
            geometry: new Point(item),
          });
          boardFeature.setStyle(commonStyle.boardStyle);
          featuresArr = [...featuresArr, boardFeature];
        });
        this.lineLayer.getSource().addFeatures([boardFeature]);
      });
    },
    //创建小车这个要素
    moveStart() {
      //坐标转换
      this.dotsData = dataArr.dataArr.map((item) => {
        return transform(item, "EPSG:3857", "EPSG:4326");
      });
      //深复制车的位置，不在原数组改变，方便重新播放
      this.carPoint = JSON.parse(JSON.stringify(this.dotsData));
      //小车最初位置在第一个坐标点
      this.feature = new Feature({
        geometry: new Point(this.carPoint[0]),
      });
      this.feature.setStyle(
        new Style({
          image: new Icon({
            src: CAR,
            scale: 0.25,
            anchor: [0.5, 0.5],
            rotation: this.countRotate(),
          }),
        })
      );
      //添加车辆元素到图层
      this.lineLayer.getSource().addFeature(this.feature);
      this.timeStart();
    },
    //计时器开始
    timeStart() {
      this.timer = setInterval(() => {
        if (this.index + 1 >= this.carPoint.length) {
          //重头开始
          this.index = 0;
          //移除要素
          this.lineLayer.getSource().removeFeature(this.feature);
          clearInterval(this.timer);
          //重复运动
          this.open(); //自动开启功能
          return;
        }
        //到转折点旋转角度
        if (this.nextPoint() === this.carPoint[this.index + 1]) {
          this.index++;
          this.feature.getStyle().getImage().setRotation(this.countRotate());
        }
        //改变坐标点
        this.feature
          .getGeometry()
          .setCoordinates(fromLonLat(this.carPoint[this.index]));
      }, 10);
    },
    //计算下一个点的位置
    //这里的算法是计算了两点之间的点   两点之间的连线可能存在很多个计算出来的点
    nextPoint() {
      let index = this.index;
      let p1 = this.map.getPixelFromCoordinate(
        fromLonLat(this.carPoint[index])
      ); //获取在屏幕的像素位置
      let p2 = this.map.getPixelFromCoordinate(
        fromLonLat(this.carPoint[index + 1])
      );
      let dx = p2[0] - p1[0];
      let dy = p2[1] - p1[1];
      //打印可见  在没有走到下一个点之前，下一个点是不变的，前一个点以这个点为终点向其靠近
      let distance = Math.sqrt(dx * dx + dy * dy);
      if (distance <= 1) {
        return this.carPoint[index + 1];
      } else {
        let x = p1[0] + dx / distance;
        let y = p1[1] + dy / distance;
        let coor = transform(
          this.map.getCoordinateFromPixel([x, y]),
          "EPSG:3857",
          "EPSG:4326"
        );
        this.carPoint[index] = coor; //这里会将前一个点重新赋值  要素利用这个坐标变化进行移动
        return this.carPoint[index];
      }
    },
    //计算两点之间的角度  算旋转角度
    countRotate() {
      let i = this.index,
        j = i + 1;
      if (j === this.carPoint.length) {
        i--;
        j--;
      }
      let p1 = this.carPoint[i];
      let p2 = this.carPoint[j];
      return Math.atan2(p2[0] - p1[0], p2[1] - p1[1]);
    },
    //弹窗
    mapClick() {
      this.map.on("singleclick", () => {
        this.overlay.setPosition(undefined);
      });
      this.map.on("contextmenu", (evt) => {
        evt.preventDefault(); //屏蔽自带的右键事件
        const coordinate = evt.coordinate; // 获取坐标
        const hbm = transform(coordinate, "EPSG:3857", "EPSG:4326");
        console.log(hbm);
        this.currentCoordinate = hbm;
        // console.log(this.$refs.coordinate);
        var feature = this.map.forEachFeatureAtPixel(
          evt.pixel,
          function (feature) {
            return feature;
          }
        );
        // console.log(feature);
        if (feature != null) {
          console.log(feature.values_.id);
          let bigDiv = this.$refs.coordinate;
          bigDiv.innerHTML = `${this.currentCoordinate}`;
          setTimeout(() => {
            this.overlay.setPosition(coordinate);
          }, 0);
        } else {
          this.overlay.setPosition(undefined);
        }
      });
    },
    //关闭弹窗
    closePopup() {
      this.overlay.setPosition(undefined);
      this.currentCoordinate = null;
    },
  },
  mounted() {
    this.initMap(); //初始化地图方法
    this.open(); //自动开启功能
  },
};
</script>

<style lang="scss" scoped>
#Map {
  width: 70vw;
  height: 100vh;
  background: rgb(0, 21, 48);
}
.open-btn {
  margin: 10px;
}
.el-button {
  position: relative;
  z-index: 99;
}
.popup {
  width: 350px;
  height: 100px;
  background: #fff;
  position: absolute;
  top: -123px;
  left: -176px;
  box-sizing: border-box;
  padding: 10px;
  &::after {
    content: "";
    display: block;
    position: absolute;
    width: 20px;
    height: 20px;
    background: #fff;
    bottom: -10px;
    left: 50%;
    transform: translateX(-50%) rotate(45deg);
  }

  .icon-close {
    position: absolute;
    top: 0px;
    right: 8px;
  }

  .content {
    margin-top: 14px;
  }
}
</style>